11. self assignment with operator=

a[i]=a[j];
*px = *py;
class Base{ /* ... */ };
class Derived: public Base{ /* ... */ };
void doSomething(const Base& rb, Derived* pd);
위와 같은 코드에서 i==j 혹은 px==py인 경우, 자기 대입을 하게 된다.
rb와 *pd가 같은 객체일 수 있다.
(자기 대입은 적법한 코드임 이를 허용하도록 구현해 주어야 한다.)

자기 대입을 하게 되었을 때, 중복 참조(aliasing)이 발생할 수 있다.
class Bitmap{ /* ... */ };
class Widget{
// ...
private:
Bitmap* pb;
};
Widget& Widget::operator=(const Widget& rhs){
delete pb;
pb=new Bitmap(*rhs.pb);
return *this;
}
위에서 *rhs.pb와 *pb가 동일한 개체일 경우, 문제가 발생한다.
이와 같은 상황을 막기 위해 일치성 검사(identity test)를 실행해 줘야 한다.
Widget& Widget::operator=(const Widget& rhs){
if(this==&rhs) return *this;
delete pb;
pb=new Bitmap(*rhs.pb);
return *this;
}
위에 코드에서 new는 예외를 발생시킬 수 있다.
아래와 같이 코드를 작성하면, new에서 예외를 발생시키더라도, 사본을 통해 동일한 동작을 수행할 수 있다.
(추가적인 일치성 검사도 필요하지 않음)
Widget& Widget::operator=(const Widget& rhs){
Bitmap* pOrig=pb;
pb=new Bitmap(*rhs.pb);
delete pOrig;
return *this;
}
copy and swap
class Widget{
// ...
void swap(Widget& rhs); // *this rhs
// ...
};
Widget& Widget::operator=(const Widget& rhs){
Widget temp(rhs); // rhs
swap(temp);
return *this;
}
값으로 인자를 전달받을 때, 사본을 생성 후 복사하기 때문에 위의 operator=와
아래 operator=는 동일하게 동작한다.
Widget& Widget::operator=(Widget rhs){ // rhs
swap(rhs);
return *this;
}